Fork me on GitHub

Java并发机制的底层实现原理

注意:所有文章除特别说明外,转载请注明出处.

[TOC]

第二章 Java并发机制的底层实现原理

2.1 volatile的应用

在多线程并发编程中 synchronize 和 volatile 扮演重要角色。 volatile 是轻量级的 synchronize ,在多处理器中保证共享变量的可见性。

如果使用 volatile 变量修饰符使用恰当,比 synchronize 的使用和执行成本更低。因为它不会引起线程上下文的切换和调度。

2.2.1 volatile定义与实现原理

定义:Java编程语言允许线程访问共享变量,为了确保共享变量能够被准确和一致地更新,线程应该确保通过排它锁单独获取这个变量。

CPU操作术语:

    1.内存屏障:是一组处理器指令,用于实现对内存操作的顺序限制。

    ...

2.2 synchronize的实现原理和应用

synchronize实现同步的基础:Java中每一个对象都可以作为锁。

1.对于普通同步方法,锁是当前实例对象。

2.对于静态同步方法,锁是当前静态类的Class对象。

3.对于同步方法块,锁是synchronize括号里配置的对象。

提示:在JVM中,代码块同步是使用monitorenter和monitorexit指令实现的。

2.2.1 Java对象头

synchronize 用的锁是存在Java对象头里。如果对象是数组类型,则虚拟机用3个字宽存储对象头,如果是非数组类型,则用2字宽存储对象头。

2.2.2 锁的升级和对比

Java 1.6中,锁有四种状态,级别从低到高是:无锁状态、偏向锁状态、轻量级锁状态、重量级锁状态。

注意:锁可以升级,不可以降级。如:偏向级锁升级成轻量级锁之后不能降为偏向锁。

1.偏向锁

当一个线程访问同步块并获取锁时,会在对象头和栈帧中的锁记录里存储锁偏向的线程ID,以后该线程在进入和退出同步块时不需要进行CAS操作来加锁和解锁,只需要简单测试下对象头的mark word里是否存有指向当前线程的偏向锁。

2.轻量级锁

线程在执行同步块之前,JVM会先在当前线程的栈帧中创建用于存储锁记录的空间,并将对象头中的 Mark Word 复制到锁记录中。然后尝试使用CAS将对象头中的 Mark Word 替换为指向锁记录的指针。如果成功,当前线程获得锁,如果失败,表示其它现车个竞争锁。

3.锁之间的对比

优点 缺点 适用场景
偏向锁 加锁和解锁不需要额外的开销,和执行非同步方法相比仅存在纳秒级差距 如果线程之间存在锁竞争,会带来额外的锁撤销的消耗 适用于一个线程访问同步块场景
轻量级锁 竞争的线程不会阻塞,提高了程序的响应速度 如果始终得不到锁竞争的线程,适用自旋会消耗CPU 追求响应时间同步块执行速度非常快
重量级锁 线程竞争不使用自旋,不会消耗CPU 线程阻塞,响应时间缓慢 追求吞吐量,同步块执行速度较长

2.3 原子操作实现原理

2.3.3 Java实现原子操作

在Java中通过锁和循环CAS的方式实现原子操作。

1.使用CAS实现原子操作

JVM中的CAS操作正是利用了处理器提供 CMPXCHG 指令实现的,自旋CAS实现的基本思路就是循环进行CAS操作直到成功为止。

提示:在Java 1.5以后,JDK的并发包提供一些类支持原子操作,如:AtomicBoolean(用原子方式更新的boolean值)、AtomicInteger(用原子方式更新int值)、AtomicInteger(用原子方式更新Long值)。

2.CAS实现原子操作的三大问题

1.ABA问题:因为CAS需要操作值时,检查值有没有发生变化,如果没有则更新,但如果值原来是A,后变成B,后又变成A,那么使用CAS进行检查时发现它的值没有发生变化,实际上变化了。

    解决:ABA问题使用版本号解决,每次更新的时候将版本号加1。在Java 1.5之后,JDK的Atomic包提供一个类 AtomicStampedReferance 解决ABA问题。

2.循环时间长开销大:自旋CAS如果长时间不成功,会给CPU带来非常大的执行开销。如果JVM提供pause指令,那么效率会提升。

3.只能保证一个共享变量的原子操作:当对一个共享变量执行操作时,我们可以使用循环CAS来保证原子操作,但是对于多个共享变量时,这时候CAS无法保证操作的原子性,这时候可以用锁。或者将多个共享变量合并成一个共享变量来操作。

3.使用锁机制来实现原子操作

锁机制保证了只有获得锁的线程才能操作锁定的内存区域。

本文标题:Java并发机制的底层实现原理

文章作者:Bangjin-Hu

发布时间:2019年10月15日 - 09:22:26

最后更新:2020年03月30日 - 08:17:39

原始链接:http://bangjinhu.github.io/undefined/第2章 Java并发机制的底层实现原理/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Bangjin-Hu wechat
欢迎扫码关注微信公众号,订阅我的微信公众号.
坚持原创技术分享,您的支持是我创作的动力.